<template>
  <div class="karaoke-line" :style="lineStyle" ref="karaokeLineRef">
    <template v-if="isLyricCharsType(lyrics)">
      <div
        v-for="(char, index) in lyrics"
        :key="index"
        class="karaoke-char"
        :style="{
          margin: charMargin,
        }"
      >
        <span class="char-base">{{ char.text }}</span>
        <span class="char-highlight" :style="highlightCharStyle(char)">{{ char.text }}</span>
      </div>
    </template>
    <template v-else-if="isLyricType(lyrics)">
      <div class="karaoke-char">
        <span class="char-base">{{ lyrics.content }}</span>
      </div>
    </template>
    <template v-else>
      <div class="karaoke-char">
        <span class="char-base" :style="{ color: activeColor }">{{ lyrics }}</span>
      </div>
    </template>
  </div>
</template>

<script setup lang="ts">
import { StyleValue, useTemplateRef, computed } from "vue";
import type { KaraokeLineProps, LyricChar } from "@/package/ass-parse/type";
import { defaultProps } from "../default";
import { useElementSize } from "@vueuse/core";
import { isLyricCharsType, isLyricType } from "@/package/ass-parse/utils";
const props = withDefaults(defineProps<KaraokeLineProps>(), defaultProps);
const karaokeLineRef = useTemplateRef("karaokeLineRef");
const size = useElementSize(karaokeLineRef);
// 计算属性
const charMargin = computed(() => `${props.charSpacing / 2}px`);

const lineStyle = computed<StyleValue>(() => ({
  fontSize: `${props.actived ? props.activeFontSize : props.fontSize}px`,
  lineHeight: `${props.lineHeight}`,
  textAlign: "center",
  fontWeight: props.fontWeight,
  color: props.actived ? props.activeColor : props.baseColor,
}));

const baseCharStyle = computed<StyleValue>(() => ({
  color: props.baseColor,
}));

const highlightCharStyle = computed(() => {
  return (char: LyricChar) =>
    ({
      color: props.highlightColor,
      textShadow: props.highlightShadow,
      width: getCharProgress(char) * 100 + "%",
    } as StyleValue);
});

// 方法
const getCharProgress = (char: LyricChar) => {
  if (char.start === undefined || char.end === undefined) {
    return 1;
  }

  // 字符尚未开始
  if (props.currentTime < char.start) {
    return 0;
  }
  // 字符已经结束
  else if (props.currentTime >= char.end) {
    return 1;
  }
  // 字符正在演唱中
  else {
    const duration = char.end - char.start;
    return (props.currentTime - char.start) / duration;
  }
};

// 通过ref获取元素的宽度和高度
const { width, height } = size;
defineExpose({
  width,
  height,
  karaokeLineEl: karaokeLineRef,
});
</script>

<style scoped>
.karaoke-line {
  width: 100%;
  position: relative;
  overflow: hidden;
}
.karaoke-char {
  display: inline-block;
  position: relative;
  margin: 0 2px;
  transition: font-size 0.3s ease-in-out;
  user-select: none;
}
.char-base {
  position: relative;
}
.char-highlight {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  overflow: hidden;
  white-space: nowrap;
  transition: "none";
}
</style>
